package com.xh.demo.controller;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.xh.demo.commons.annotation.NotRepeatSubmit;
import com.xh.demo.commons.consts.RConst;
import com.xh.demo.commons.entity.*;
import com.xh.demo.commons.utils.SignUtil;
import com.xh.demo.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/api")
public class TokenController {

    @Autowired
    private RedisService redisService;

    /**
     * API Token
     */
    @PostMapping("/token")
    public ApiResponse<AccessToken> apiToken(String appId, @RequestHeader("timestamp") String timestamp, @RequestHeader("sign") String sign) {
        Assert.isFalse(StrUtil.isEmpty(appId) || StrUtil.isEmpty(timestamp) || StrUtil.isEmpty(sign), "参数错误");
        long requestInterval = System.currentTimeMillis() - Long.parseLong(timestamp);
        Assert.isTrue(requestInterval < RConst.Time.TIME_5_MINUTE, "请求过期，请重新请求");
        // 1. TODO 根据appId查询数据库获取appSecret
        AppInfo appInfo = new AppInfo("1", "12345678954556", Boolean.FALSE);
        Assert.isFalse(appInfo.getDisabled(), "账号已禁用");
        // 2. 校验签名
        String signature = SignUtil.sign(timestamp, appId, appInfo.getAppSecret());
        log.info(signature);
        Assert.isTrue(signature.equals(sign), "签名错误");
        // 3. 如果正确生成一个token保存到redis中，如果错误返回错误信息
        AccessToken accessToken = this.saveToken(appInfo);
        return ApiResponse.success(accessToken);
    }

    @NotRepeatSubmit
    @PostMapping("user_token")
    public ApiResponse<UserInfo> userToken(String username, String password) {
        // TODO 根据用户名查询密码, 并比较密码(密码可以RSA加密一下)
        UserInfo userInfo = new UserInfo(username, "81255cb0dca1a5f304328a70ac85dcbd", "111111");
        String pwd = password + userInfo.getSalt();
        String passwordMD5 = SignUtil.MD5Util.encode(pwd);
        Assert.isTrue(passwordMD5.equals(userInfo.getPassword()), "密码错误");
        // 2. 保存Token
        AppInfo appInfo = new AppInfo("1", "12345678954556", Boolean.FALSE);
        AccessToken accessToken = this.saveToken(appInfo, userInfo);
        userInfo.setAccessToken(accessToken);
        return ApiResponse.success(userInfo);
    }

    private AccessToken saveToken(AppInfo appInfo) {
        return this.saveToken(appInfo, null);
    }

    private AccessToken saveToken(AppInfo appInfo, UserInfo userInfo) {
        String token = UUID.randomUUID().toString();
        // token有效期为2小时
        long expireTime = System.currentTimeMillis() + RConst.Time.TIME_2_HOUR;
        // 4. 保存token
        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setAppInfo(appInfo);
        if (Objects.isNull(userInfo)) {
            tokenInfo.setTokenType(RConst.Num.INT_0);
        } else {
            tokenInfo.setUserInfo(userInfo);
            tokenInfo.setTokenType(RConst.Num.INT_1);
        }
        redisService.setJSON(token, tokenInfo, appInfo.getExpireTime(), TimeUnit.SECONDS);
        return new AccessToken(token, expireTime);
    }

    public static void main(String[] args) {
        long timestamp = System.currentTimeMillis();
        System.out.println(timestamp);
        String signString = timestamp + "1" + "12345678954556";
        String sign = SignUtil.MD5Util.encode(signString);
        System.out.println(sign);

        System.out.println("-------------------");
        signString = "password=123456&username=1&12345678954556" + "ff03e64b-427b-45a7-b78b-47d9e8597d3b1529815393153sdfsdfsfs" + timestamp + "A1scr6";
        sign = SignUtil.MD5Util.encode(signString);
        System.out.println(sign);
    }
}